/*
 * test.cpp
 *
 *  Created on: May 3, 2014
 *      Author: Lhmily
 */
#include "header/base.h"
#include <cstring>

#define DEFAULT_SIZE 1000000

void help();

template<typename Elem>
void check(Elem array[], int arraysize, int listsize);

template<typename Comp>
double get_runtime(int *array, int arraysize, int listsize);

template<typename Comp>
int testMain(int argc, char **argv) {
	int* array_random, *array_asc, *array_dsc;
	int i;

	int arraysize;
	int listsize;

	//srand((unsigned) time(NULL));

	if (argc > 3)
		help();

	switch (argc) {
	case 3:
		listsize = atoi(argv[2]);
		arraysize = atoi(argv[1]);
		break;
	case 2:
		if (strcmp(argv[1], "help") == 0)
			help();
		listsize = arraysize = atoi(argv[1]);
		break;
	default:
		listsize = arraysize = DEFAULT_SIZE;
	}

	if (arraysize <= 0) {
		cout << "Array size must be positive" << endl;
		exit(-1);
	}

	if (listsize < 0) {
		cout << "Selected list size can not be negative" << endl;
		exit(-1);
	}
	if (listsize > arraysize)
		listsize = arraysize;

	array_random = new int[arraysize];
	array_asc = new int[arraysize];
	array_dsc = new int[arraysize];

	for (i = 0; i < arraysize; i++)
		array_dsc[i] = arraysize - i;  // Reverse sorted

	for (i = 0; i < arraysize; i++)
		array_random[i] = rand();  // Random

	for (i = 0; i < arraysize; i++)
		array_asc[i] = i;  // Sorted

	cout << endl << argv[0] << " : the list size " << listsize
			<< ", array size " << arraysize << endl;
	for (i = 0; i < 3; ++i) {
		switch (i) {
		case 0:  //asc
			cout << endl << "\t1: original order is sorted, and time is "
					<< get_runtime<Comp>(array_asc, arraysize, listsize)
					<< " seconds" << endl;
			break;
		case 1:  //dsc
			cout << endl << "\t2: original order is reverse order, and time is "
					<< get_runtime<Comp>(array_dsc, arraysize, listsize)
					<< " seconds" << endl;
			break;
		default:  //random
			cout << endl << "\t3: original order is random, and time is "
					<< get_runtime<Comp>(array_random, arraysize, listsize)
					<< " seconds" << endl;
		}
	}

	return 0;
}

void help() {
	cout << "Usage: <sortname> [array_size] [size]" << endl
			<< "--array_size default value is RAND_MAX" << endl
			<< "--size default value is array" << endl;
	exit(-1);
}
template<typename Elem>
void check(Elem array[], int arraysize, int listsize) {
	for (int i = 0; i < arraysize; i += listsize)
		for (int j = i + 1; j < i + listsize; j++)
			if (array[j - 1] > array[j])
				cout << "ERROR!!!" << "j=" << j << endl;
}

template<typename Comp>
double get_runtime(int *array, int arraysize, int listsize) {
	double ret_val = 0.0;
	clock_t tstart = clock();
	for (int it = 0; it < arraysize; it += listsize) {
		sort<int, Comp>(&array[it], listsize);
	}
	ret_val = (double) (clock() - tstart) / (double) CLOCKS_PER_SEC;
	check(array, arraysize, listsize);
	return ret_val;
}
